﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using System.Text.RegularExpressions;

namespace PMisuseAn.io
{
    class HistorySerialisationEngine
    {
        static string activeDir = @"..\..\interactionHistory";
        
        static string newPath = "";
        static string newFileName = "";
        static string _sourceAgentName = "";

        public static void serialise(string interactionSeqNo,string sourceAgentName, HistoryItem hi)
        {
            if (!Directory.Exists(activeDir))
            {
                Directory.CreateDirectory(activeDir);
            }

            newPath = System.IO.Path.Combine(activeDir, sourceAgentName);
            _sourceAgentName = sourceAgentName;
            if (!Directory.Exists(newPath))
            {
                Directory.CreateDirectory(newPath);
            }

            newFileName = interactionSeqNo;
            newPath = System.IO.Path.Combine(newPath, newFileName);

            if (!File.Exists(newPath))
            {
                FileStream fs = null;
                try
                {
                    fs = File.Create(newPath);

                }
                finally
                {
                    fs.Dispose();
                    GC.Collect();
                    fs.Close();
                }
                
            }

            Stream stream = null;
            try
            {
                stream = File.Open(newPath, FileMode.Create);
                BinaryFormatter bformatter = new BinaryFormatter();

                bformatter.Serialize(stream, hi);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Dispose();
                    stream.Close();
                }
            }           
        }

        public static HistoryItem deSerialiseInteractionHistory(int interactionSeqNo, string sourceAgentName)
        //public static HistoryItem deSerialiseInteractionHistory(string interactionSeqNo, string sourceAgentName)
        {
            if (!Directory.Exists(activeDir))
            {
                Directory.CreateDirectory(activeDir);
            }

            newPath = System.IO.Path.Combine(activeDir, sourceAgentName);
            _sourceAgentName = sourceAgentName;
            newFileName = ""+interactionSeqNo;
            string newPathx = System.IO.Path.Combine(newPath, newFileName);
            //string newPathx = interactionSeqNo;
            
            HistoryItem ih = null;
            bool deserialised = false;
            int counter = 0;
            while (!deserialised && counter < 100)
            {
                Stream stream = null;
                try
                {
                    counter++;
                    stream = File.Open(newPathx, FileMode.Open, FileAccess.Read, FileShare.None);
                    BinaryFormatter bformatter = new BinaryFormatter();

                    ih = (HistoryItem)bformatter.Deserialize(stream);
                    deserialised = true;
                }
                catch
                {
                    //If it cannot serialise catch 
                } 
                finally
                {
                    if (stream != null)
                    {
                        stream.Dispose();
                        GC.Collect();
                        stream.Close();
                    }
                }

            }
            if (counter > 100)
                throw new Exception("Unable to deserialise file!"); 
            
            return ih;
        }
        
        public static string[] getInteractionList()
        {
            newPath = System.IO.Path.Combine(activeDir, _sourceAgentName);

            string[] interactionNames = null;
            if (Directory.Exists(newPath))
            {
                interactionNames = Directory.GetFiles(newPath);
            }
                        
            return interactionNames;
        }


        public static Stack<int> getStackedInteractionList(string sourceAgentName)
        {
            newPath = System.IO.Path.Combine(activeDir, sourceAgentName);

            string[] interactionNames = null;
            if (Directory.Exists(newPath))
            {
                interactionNames = Directory.GetFiles(newPath);
            }

            Stack<int> stackedInteractions = new Stack<int>();
            if (interactionNames != null)
            {
                int[] intseq = retrieveInteractionSeqNos(interactionNames);

                foreach (int isq in intseq)
                {
                    stackedInteractions.Push(isq);
                }
            }
            
            return stackedInteractions;
        }

        public static Stack<int> getStackedInteractionList()
        {
            newPath = System.IO.Path.Combine(activeDir, _sourceAgentName);

            string[] interactionNames = null;
            if (Directory.Exists(newPath))
            {
                interactionNames = Directory.GetFiles(newPath);
            }

            Stack<int> stackedInteractions = new Stack<int>();
            if (interactionNames != null)
            {
                int[] intseq = retrieveInteractionSeqNos(interactionNames);

                foreach (int isq in intseq)
                {
                    stackedInteractions.Push(isq);
                }
            }
            
            return stackedInteractions;
        }


        public static int[] retrieveInteractionSeqNos(string[] interactionNames)
        {
            int[] interactionSeqNos = new int[interactionNames.Count()];
            int i = 0;
            foreach(string intna in interactionNames)
            {
                string[] words = Regex.Split(intna, @"\\");
                string st = words[words.Count() - 1];
                int x = Int16.Parse(st);
                interactionSeqNos[i] = x;
                i = i+1;
            }

            Array.Sort(interactionSeqNos);
            return interactionSeqNos;
        }

        public static int totalInteractions()
        {
            newPath = System.IO.Path.Combine(activeDir, _sourceAgentName);

            string[] interactionNames = null;
            if (Directory.Exists(newPath))
            {
                interactionNames = Directory.GetFiles(newPath);
                return interactionNames.Count();
            }

            return 0;
        }
    }
}
